#include "Client.h"
Client::Client(const string &ip, int port) : server_ip(ip), server_port(port)
{
}

void Client::closeConnection()
{
	if (client_fd >= 0)
	{
		close(client_fd); // 关闭客户端连接
		client_fd = -1;
	}
}
Client::~Client()
{
	closeConnection();
}

// 连接服务器
bool Client::connectToServer()
{
	// 创建客户端套接字，AF_INET 表示使用 IPv4 协议，SOCK_STREAM 表示使用 TCP
	client_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (client_fd == -1)
	{
		cout << "创建客户端套接字失败" << endl;
		return false;
	}
	// 创建结构体--存储服务器的相关信息
	sockaddr_in server_addr{};
	server_addr.sin_family = AF_INET; // 使用 IPv4
	// 网络字节序是一种统一的字节序，保证不同主机间数据传输的正确性
	server_addr.sin_port = htons(server_port); // 端口号，使用网络字节序
	// 将 服务端的 IP 地址转换为网络字节序并存储
	// 将人类可读的 IP 地址字符串转换为计算机网络通信所需的二进制地址
	if (-1 == (inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr)))
	{
		cout << "不合法的地址" << endl;
		close(client_fd);
		return false;
	}

	// 连接服务器
	if (connect(client_fd, (sockaddr *)&server_addr, sizeof(server_addr)) < 0)
	{
		std::cerr << "连接失败" << std::endl;
		close(client_fd);
		return false;
	}
	// 如果连接成功
	cout << "成功连接到--" << server_ip << ":" << server_port << endl;
	return true;
}

// 接收服务器发送的数据
string Client::receiveData(std::string &data)
{
	if (client_fd < 0)
	{
		cout << "没有建立连接的客户端" << endl;
		return "";
	}

	char buffer[1024];
	memset(buffer, 0, sizeof(buffer));
	ssize_t bytes_received = recv(client_fd, buffer, sizeof(buffer), 0);
	if (bytes_received < 0)
	{
		cout << "接收失败" << endl;
		return "";
	}
	else if (bytes_received == 0)
	{
		std::cout << "连接被服务器关闭" << std::endl;
		return "";
	}
	return string(buffer, bytes_received);
}

// 向服务器发送数据
void Client::sendData(const std::string &data)
{
	ssize_t bytes_sent = send(client_fd, data.c_str(), data.size(), 0);
	if (bytes_sent < 0)
	{
		std::cerr << "发送数据失败" << std::endl;
	}
	else
	{
		std::cout << "Sent: " << bytes_sent << " bytes to server." << std::endl;
	}
}

// 重载 << 操作符，向服务器发送数据
Client &Client::operator<<(const std::string &data)
{
	sendData(data);
	return *this;
}

// 重载 >> 操作符，从服务器接收数据
Client &Client::operator>>(std::string &data)
{
	data = receiveData(data);
	return *this;
}
